package mongodb

import (
	"context"
	"fmt"
	"gitee.com/Cauchy_AQ/vxopen/model"
	chat "gitee.com/Cauchy_AQ/vxopen/model/mongodb/chat"
	role "gitee.com/Cauchy_AQ/vxopen/model/mongodb/role"
	user "gitee.com/Cauchy_AQ/vxopen/model/mongodb/user"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/redis"
	"sync"
)

// 导出使用
type (
	User = user.User
	Role = role.Role
	Chat = chat.Chat
)

var (
	ErrNotFound = user.ErrNotFound
)

var (
	mongoClient *Mongo
	once        sync.Once
)

type Mongo struct {
	URL     string
	UserCol user.UserModel
	RoleCol role.RoleModel
	ChatCol chat.ChatModel
}

func GetMongoInstance(conf model.ModelConfig) *Mongo {
	once.Do(func() {
		mongoClient = &Mongo{
			URL: getUrl(conf.MongoConfig),
		}
		// User Collection
		mongoClient.UserCol = mongoClient.GetUserCollectionWithCache(conf.RedisConfig)
		mongoClient.RoleCol = mongoClient.GetRoleCollectionWithCache(conf.RedisConfig)
		mongoClient.ChatCol = mongoClient.GetChatCollectionWithCache(conf.RedisConfig)

		AfterCreateRole(mongoClient)
	})
	return mongoClient
}

func (m *Mongo) GetUserCollectionWithCache(redisConfig model.RedisConfig) user.UserModel {
	return user.NewUserModel(m.URL, "login", "userinfo", cache.CacheConf{
		cache.NodeConf{
			RedisConf: getCacheConf(redisConfig),
			Weight:    100,
		},
	})
}

func (m *Mongo) GetRoleCollectionWithCache(redisConfig model.RedisConfig) role.RoleModel {
	return role.NewRoleModel(m.URL, "login", "roleinfo", cache.CacheConf{
		cache.NodeConf{
			RedisConf: getCacheConf(redisConfig),
			Weight:    100,
		},
	})
}

func (m *Mongo) GetChatCollectionWithCache(redisConfig model.RedisConfig) chat.ChatModel {
	return chat.NewChatModel(m.URL, "login", "chatinfo", cache.CacheConf{
		cache.NodeConf{
			RedisConf: getCacheConf(redisConfig),
			Weight:    100,
		},
	})
}

// AfterCreateRole 在任意数据库操作后，立即执行角色表的初始化
func AfterCreateRole(mongo *Mongo) {
	data := &role.Role{
		Name:       "普通用户",
		Permission: []string{"home"},
	}
	if err := mongo.RoleCol.Insert(context.Background(), data); err != nil {
		panic(err)
	}
}

func getUrl(mongoConfig model.MongoConfig) string {
	return fmt.Sprintf("mongodb://%s:%d", mongoConfig.Host, mongoConfig.Port)
}

func getCacheConf(redisConfig model.RedisConfig) redis.RedisConf {
	return redis.RedisConf{
		Host: fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port),
		Pass: redisConfig.Password,
		Type: "node",
	}
}
